#include "wifi_at.h"

extern char wifiATCmdString[WIFI_AT_CMD_MAX_LEN]; // AT指令字符串

/*
*AT+CWMODE_CUR—设置当前 Wi-Fi 模式，不保存到 Flash
*测试指令：
AT+CWMODE_CUR=1
+CWMODE_CUR:<mode> 取值列表
OK
*查询指令：
AT+CWMODE_CUR?
+CWMODE_CUR:<mode>
OK
*设置指令：
AT+CWMODE_CUR=<mode>
<mode>：
‣ 1：Station 模式
‣ 2：SoftAP 模式
‣ 3：SoftAP+Station 模式
*示例：AT+CWMODE_CUR=3
*
*AT+CWMODE_DEF一设置当前 Wi-Fi 模式并保存到 Flash
*测试指令：
AT+CWMODE_DEF=1
+CWMODE_DEF:<mode> 取值列表
OK
*查询指令：
AT+CWMODE_DEF?
+CWMODE_DEF:<mode>
OK
*设置指令：
AT+CWMODE_DEF=<mode>
<mode>：
‣ 1：Station 模式
‣ 2：SoftAP 模式
‣ 3：SoftAP+Station 模式
*示例：AT+CWMODE_DEF=3
*
*cmdType: 0:测试指令 1:查询指令，2:设置指令
*saveType: 0:不保存到Flash 1:保存到Flash
*/
void moduleCWMODE(uint8_t cmdType, uint8_t saveType, char *mode)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
        memcpy(wifiATCmdString, WIFI_AT_CWMODE_DEF, sizeof(WIFI_AT_CWMODE_DEF));
    else
        memcpy(wifiATCmdString, WIFI_AT_CWMODE_CUR, sizeof(WIFI_AT_CWMODE_CUR));
    switch (cmdType)
    {
    case 0:
    {
        strcat(wifiATCmdString, "=?");
    }
    break;
    case 1:
    {
        strcat(wifiATCmdString, "?");
    }
    break;
    case 2:
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, mode);
    }
    break;
    default:
        break;
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWJAP_CUR—临时连接 AP
本设置不不保存到 Flash。
*查询指令：
AT+CWJAP_CUR?
*
+CWJAP_CUR:<ssid>,<bssid>,<channel>,<rssi>
OK
*
• <ssid>：字符串串参数，AP 的 SSID
• <bssid>：AP 的 MAC 地址
• <channel>：信道号
• <rssi>：信号强度
*设置指令：
AT+CWJAP_CUR=<ssid>,<pwd>,[<bssid>][,<pci_en>]
*
OK
或者
+CWJAP_CUR:<error code>
FAIL
*
• <ssid>：⽬目标 AP 的 SSID
• <pwd>：密码最⻓长 64 字节 ASCII
• [<bssid>]：选填参数，⽬目标 AP 的 MAC 地址，⼀一
般⽤用于有多个 SSID 相同的 AP 的情况
• [<pci_en>]：选填参数，不不允许连接 WEP 和 open
的路路由器器，可⽤用于 PCI 认证
• <error code>：（仅供参考，并不不可靠）
‣ 1：连接超时
‣ 2：密码错误
‣ 3：找不不到⽬目标 AP
‣ 4：连接失败
参数设置需要开启 Station 模式，若 SSID 或者password 中含有特殊符号，例例如 , 或者 “ 或者 \ 时，
需要进⾏行行转义，其它字符转义⽆无效。
*示例：
AT+CWJAP_CUR="abc","0123456789"
例例如，⽬目标 AP 的 SSID 为 "ab\,c"，password 为 "0123456789"\"，则指令如下：
AT+CWJAP_CUR="ab\\\,c","0123456789\"\\"
如果有多个 AP 的 SSID 均为 "abc"，可通过 BSSID 确定⽬目标 AP：
AT+CWJAP_CUR="abc","0123456789","ca:d7:19:d8:a6:44"
*
*AT+CWJAP DEF一连接 AP，保存到 Flash
*查询指令：
AT+CWJAP_DEF?
*
+CWJAP_CUR:<ssid>,<bssid>,<channel>,<rssi>
OK
*
• <ssid>：字符串串参数，AP 的 SSID
• <bssid>：AP 的 MAC 地址
• <channel>：信道号
• <rssi>：信号强度
*设置指令：
AT+CWJAP_CUR=<ssid>,<pwd>,[<bssid>][,<pci_en>]
*
OK
或者
+CWJAP_CUR:<error code>
FAIL
*
• <ssid>：⽬目标 AP 的 SSID
• <pwd>：密码最⻓长 64 字节 ASCII
• [<bssid>]：选填参数，⽬目标 AP 的 MAC 地址，⼀一
般⽤用于有多个 SSID 相同的 AP 的情况
• [<pci_en>]：选填参数，不不允许连接 WEP 和 open
的路路由器器，可⽤用于 PCI 认证
• <error code>：（仅供参考，并不不可靠）
‣ 1：连接超时
‣ 2：密码错误
‣ 3：找不不到⽬目标 AP
‣ 4：连接失败
参数设置需要开启 Station 模式，若 SSID 或者password 中含有特殊符号，例例如 , 或者 “ 或者 \ 时，
需要进⾏行行转义，其它字符转义⽆无效。
*示例：
AT+CWJAP_DEF="abc","0123456789"
例例如，⽬目标 AP 的 SSID 为 "ab\,c"，password 为 "0123456789"\"，则指令如下：
AT+CWJAP_DEF="ab\\\,c","0123456789\"\\"
如果有多个 AP 的 SSID 均为 "abc"，可通过 BSSID 确定⽬目标 AP：
AT+CWJAP_DEF="abc","0123456789","ca:d7:19:d8:a6:44"
*
*cmdType: 0:查询指令，1:设置指令
*saveType: 0:不保存到Flash 1:保存到Flash
*/
void moduleCWJAP_CUR(uint8_t cmdType, uint8_t saveType, char *ssid, char *pwd, char *bssid, char *pci_en)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
        memcpy(wifiATCmdString, WIFI_AT_CWJAP_DEF, sizeof(WIFI_AT_CWJAP_DEF));
    else
        memcpy(wifiATCmdString, WIFI_AT_CWJAP_CUR, sizeof(WIFI_AT_CWJAP_CUR));
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, ssid);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, pwd);
        if (bssid != NULL)
        {
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, bssid);
            strcat(wifiATCmdString, ",");
            strcat(wifiATCmdString, pci_en);
        }
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
 *AT+CWLAPOPT—设置 CWLAP 指令的属性
 *AT+CWLAPOPT=<sort_enable>,<mask>
 • <sort_enable>：指令 AT+CWLAP 的扫描结果是否按照信号强度 RSSI 值排序：
‣ 0：不不排序
‣ 1：为根据 RSSI 排序
• <mask>：对应 bit 若为 1，则指令 AT+CWLAP 的扫描结果显示相关属性，对应 bit 若为 0，则不不显
示。具体如下：
‣ bit 0：设置 AT+CWLAP 的扫描结果是否显示 <ecn>
‣ bit 1：设置 AT+CWLAP 的扫描结果是否显示 <ssid>
‣ bit 2：设置 AT+CWLAP 的扫描结果是否显示 <rssi>
‣ bit 3：设置 AT+CWLAP 的扫描结果是否显示 <mac>
‣ bit 4：设置 AT+CWLAP 的扫描结果是否显示 <channel>
‣ bit 5：设置 AT+CWLAP 的扫描结果是否显示 <freq offset>
‣ bit 6：设置 AT+CWLAP 的扫描结果是否显示 <freq calibration>
‣ bit 7：设置 AT+CWLAP 的扫描结果是否显示 <pairwise_cipher>
‣ bit 8：设置 AT+CWLAP 的扫描结果是否显示 <group_cipher>
‣ bit 9：设置 AT+CWLAP 的扫描结果是否显示 <bgn>
‣ bit 10：设置 AT+CWLAP 的扫描结果是否显示 <wps>
*示例：
AT+CWLAPOPT=1,2047
第⼀一个参数为 1，表示后续如果使⽤用 AT+CWLAP 指令，扫描结果将按照信号强度 RSSI 值排序；
第⼆二个参数为 2047，即 0x7FF，表示 <mask> 的相关 bit 全部置为 1，后续如果使⽤用 AT+CWLAP 指
令，扫描结果将显示所有参数。
*/
void moduleCWLAPOPT(char *sort_enable, char *mask)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CWLAPOPT, sizeof(WIFI_AT_CWLAPOPT));
    strcat(wifiATCmdString, sort_enable);
    strcat(wifiATCmdString, ",");
    strcat(wifiATCmdString, mask);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWLAP—扫描当前可⽤用的 AP
*设置指令：
AT+CWLAP=<ssid>[,<mac>,<channel>,<scan_type>,<scan_time_min>,<scan_time_max>]
*
+CWLAP:<ecn>,<ssid>,<rssi>,<mac>,<channel>,<freq offset>,<freqcali>,<pairwise_cipher>,<group_cipher>,<bgn>,<wps>
OK
*执行指令：
*AT+CWLAP
*+CWLAP:<ecn>,<ssid>,<rssi>,<mac>,<channel>,<freq offset>, <freq cali>,<pairwise_cipher>,<group_cipher>,<bgn>,<wps>
OK
*
• [<scan_type>] : 选填参数
‣ 0: active scan
‣ 1: passive scan
• [<scan_time_min>] : 选填参数，单位 ms，范围 [0,1500]
‣ 对于 active scan，此参数为每个信道的最⼩小扫描时间；默认值为 0；
‣ 对于 passive scan，此参数⽆无效
• [<scan_time_max>] : 选填参数，单位 ms，范围 [0,1500]
‣ 对于 active scan，此参数为每个信道的最⼤大扫描时间；当设置为 0 时，采⽤用默认值 120ms;
‣ 对于 passive scan，此参数为每个信道扫描的时间；默认值为 360ms
• <ecn>：加密⽅方式
‣ 0：OPEN
‣ 1：WEP
‣ 2：WPA_PSK
‣ 3：WPA2_PSK
‣ 4：WPA_WPA2_PSK
‣ 5：WPA2_Enterprise（⽬目前 AT 不不⽀支持连接这种加密 AP）
• <ssid>：字符串串参数，AP 的 SSID
• <rssi>：信号强度
• <mac>：字符串串参数，AP 的 MAC 地址
• <channel>：信道号
• <freq offset>：AP 频偏，单位：kHz。此数值除以 2.4，可得到 ppm 值
• <freq cali>：频偏校准值
• <pairwise_cipher>:
‣ 0：CIPHER_NONE
‣ 1：CIPHER_WEP40
‣ 2：CIPHER_WEP104
‣ 3：CIPHER_TKIP
‣ 4：CIPHER_CCMP
‣ 5：CIPHER_TKIP_CCMP
‣ 6：CIPHER_UNKNOWN
• <group_cipher>: 定义与 <pairwise_cipher> 相同
• <bgn>:
‣ bit0 代表 b 模式; bit1 代表 g 模式; bit2 代表 n 模式
‣ 若对应 bit 为 1，表示该模式使能；若对应 bit 为 0，则该模式未使能。
• <wps>：0，WPS 未使能；1，WPS 使能
• scan_time_min 不不能⼤大于 scan_time_max，即要求 scan_time_max >= scan_time_min。
• 若 scan_time_min 和 scan_time_max 设置均为 0，则采⽤用默认值，默认值具体如下：
‣ 对于 active scan，每个信道的最⼩小扫描时间是 0，最⼤大扫描时间是 120ms
‣ 对于 passive scan，每个信道扫描的时间是 360ms
*示例：
AT+CWLAP="WiFi","ca:d7:19:d8:a6:44",6,0,50,120,
或者查找指定 SSID 的 AP：
AT+CWLAP="WiFi"
或者使能 passive scan 模式：
AT+CWLAP=,,,1,,
*
*cmdType:0表示设置，1表示执行
*/
void moduleCWLAP(char *ssid, char *mac, char *channel, char *scan_type, char *scan_time_min, char *scan_time_max, uint8_t cmdType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CWLAP, sizeof(WIFI_AT_CWLAP));
    if (cmdType == 0)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, ssid);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, mac);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, channel);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, scan_type);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, scan_time_min);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, scan_time_max);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWSAP_CUR—配置 ESP8266 SoftAP 当前参数, 设置不不保存到 Flash。
*查询指令：
AT+CWSAP_CUR?
*返回值：
+CWSAP_CUR:<ssid>,<pwd>,<chl>,<ecn>,<max conn>,<ssid hidden>
*设置指令：指令只有在 SoftAP 模式开启后有效。
AT+CWSAP_CUR=<ssid>,<pwd>,<chl>,<ecn>[,<max conn>][,<ssid hidden>]
*
OK
或
ERROR
*
• <ssid>：字符串串参数，接⼊入点名称
• <pwd>：字符串串参数，密码⻓长度范围：8 ~ 64 字节
ASCII
• <chl>：通道号
• <ecn>：加密⽅方式，不不⽀支持 WEP
‣ 0：OPEN
‣ 2：WPA_PSK
‣ 3：WPA2_PSK
‣ 4：WPA_WPA2_PSK
• [<max conn>]（选填参数）：允许连⼊入 ESP8266
SoftAP 的最多 Station 数⽬目，取值范围 [1, 8]。
• [<ssid hidden>]（选填参数）：默认为 0，开启
⼴广播 ESP8266 SoftAP SSID。
‣ 0：⼴广播 SSID
‣ 1：不不⼴广播 SSID
*示例：
AT+CWSAP_CUR="ESP8266","1234567890",5,3
*
*
*AT+CWSAP DEF一配置 ESP8266 SoftAP 当前参数，保存到 Flash
*查询指令：设置保存到 Flash system parameter 区域。
AT+CWSAP_DEF?
*返回值：
+CWSAP_DEF:<ssid>,<pwd>,<chl>,<ecn>,<max conn>,<ssid hidden>
*设置指令：指令只有在 SoftAP 模式开启后有效。
AT+CWSAP_DEF=<ssid>,<pwd>,<chl>,<ecn>[,<max conn>][,<ssid hidden>]
*
• <ssid>：字符串串参数，接⼊入点名称
• <pwd>：字符串串参数，密码⻓长度范围：8 ~ 64 字节
ASCII
• <chl>：通道号
• <ecn>：加密⽅方式，不不⽀支持 WEP
‣ 0：OPEN
‣ 2：WPA_PSK
‣ 3：WPA2_PSK
‣ 4：WPA_WPA2_PSK
• [<max conn>]（选填参数）：允许连⼊入 ESP8266
SoftAP 的最多 Station 数⽬目，取值范围 [1, 8]。
• [<ssid hidden>]（选填参数）：默认为 0，开启
⼴广播 ESP8266 SoftAP SSID。
‣ 0：⼴广播 SSID
‣ 1：不不⼴广播 SSID
*示例：
AT+CWSAP_DEF="ESP8266","1234567890",5,3
*
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到Flash，1表示保存到Flash
*/
void moduleCWSAP(char *ssid, char *pwd, char *chl, char *ecn, char *max_conn, char *ssid_hidden, uint8_t cmdType, uint8_t saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CWSAP_DEF, sizeof(WIFI_AT_CWSAP_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CWSAP_CUR, sizeof(WIFI_AT_CWSAP_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, ssid);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, pwd);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, chl);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, ecn);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, max_conn);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, ssid_hidden);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWLIF—查询连接到 ESP8266 SoftAP 的 Station 信息
*
+CWLIF:<ip addr>,<mac>
OK
*
• <ip addr>：连接到 ESP8266 SoftAP 的 Station IP 地址
• <mac>：连接到 ESP8266 SoftAP 的 Station MAC 地址
*本指令⽆无法查询静态 IP，仅⽀支持在 ESP8266 SoftAP 和连⼊入的 Station DHCP 均使能的情况下有效。
*/

/*
*AT+CWDHCP CUR一设置 DHCP，不保存到 Flash
*查询指令：
AT+CWDHCP_CUR?
*返回值：0或者1(即DHCP是否使能)
• Bit0：
‣ 0：SoftAP DHCP 关闭
‣ 1：SoftAP DHCP 开启
• Bit1：
‣ 0：Station DHCP 关闭
‣ 1：Station DHCP 开启
*
*设置指令：
AT+CWDHCP_CUR=<mode>,<en>
*
OK
*
• <mode>：
‣ 0：设置 ESP8266 SoftAP
‣ 1：设置 ESP8266 Station
‣ 2：设置 ESP8266 SoftAP 和 Station
• <en>：
‣ 0：关闭 DHCP
‣ 1：开启 DHCP
*
• 本设置不不保存到 Flash。
• 本设置指令与设置静态 IP 的指令（AT+CIPSTA 系列列和 AT+CIPAP 系列列）互相影响：
‣ 设置使能 DHCP，则静态 IP ⽆无效；
‣ 设置静态 IP，则 DHCP 关闭；
‣ 以最后的设置为准。
*示例：
AT+CWDHCP_CUR=0,1
*
*
*AT+CWDHCP_DEF一设置 DHCP，保存到 Flash
*查询指令：
AT+CWDHCP_DEF?
*返回值：0或者1(即DHCP是否使能)
• Bit0：
‣ 0：SoftAP DHCP 关闭
‣ 1：SoftAP DHCP 开启
• Bit1：
‣ 0：Station DHCP 关闭
‣ 1：Station DHCP 开启
*
*设置指令：
AT+CWDHCP_DEF=<mode>,<en>
*
OK
*
• <mode>：
‣ 0：设置 ESP8266 SoftAP
‣ 1：设置 ESP8266 Station
‣ 2：设置 ESP8266 SoftAP 和 Station
• <en>：
‣ 0：关闭 DHCP
‣ 1：开启 DHCP
*
• 本设置不不保存到 Flash。
• 本设置指令与设置静态 IP 的指令（AT+CIPSTA 系列列和 AT+CIPAP 系列列）互相影响：
‣ 设置使能 DHCP，则静态 IP ⽆无效；
‣ 设置静态 IP，则 DHCP 关闭；
‣ 以最后的设置为准。
*示例：
AT+CWDHCP_DEF=0,1
*
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到Flash，1表示保存到Flash
*/
void moduleCWDHCP(char *mode, char *en, uint8_t cmdType, uint8_t saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CWDHCP_DEF, sizeof(WIFI_AT_CWDHCP_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CWDHCP_CUR, sizeof(WIFI_AT_CWDHCP_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, mode);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, en);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWDHCPS_CUR—设置 ESP8266 SoftAP DHCP 分配的 IP 范围，不不保存到 Flash
• 本设置不不保存到 Flash。
• 本指令必须在 ESP8266 SoftAP 模式使能，且开启 DHCP 的情况下使⽤用，设置的 IP 范
围必须与 ESP8266 SoftAP 在同⼀一⽹网段。
*查询指令：
AT+CWDHCPS_CUR?
*返回值：
+CWDHCPS_CUR=<lease time>,<start IP>,<end IP>
*设置指令：
AT+CWDHCPS_CUR=<enable>,<lease time>,<start IP>,<end IP>
*返回值：
OK
*参数说明
• <enable>：
‣ 0：清除设置 IP 范围，恢复默认值，后续参数⽆无需填写
‣ 1：使能设置 IP 范围，后续参数必须填写
• <lease time>：租约时间，单位：分钟，取值范围 [1, 2880]
• <start IP>：DHCP 服务器器 IP 池的起始 IP
• <end IP>：DHCP 服务器器 IP 池的结束 IP
*示例：
AT+CWDHCPS_CUR=1,3,"192.168.4.10","192.168.4.15"
或者
AT+CWDHCPS_CUR=0 //清除设置，恢复默认值
*
*
*AT+CWDHCPS DEF-设置 ESP8266 SoftAP DHCP 分配的 IP 范围，保存到 Flash
• 本设置保存到 Flash ⽤用户参数区。
• 本指令必须在 ESP8266 SoftAP 模式使能，且开启 DHCP 的情况下使⽤用，设置的 IP 范
围必须与 ESP8266 SoftAP 在同⼀一⽹网段。
*查询指令：
AT+CWDHCPS_DEF?
*返回值：
+CWDHCPS_DEF=<lease time>,<start IP>,<end IP>
*设置指令：
AT+CWDHCPS_DEF=<enable>,<lease time>,<start IP>,<end IP>
*返回值：
OK
*参数说明:
• <enable>：
‣ 0：清除设置 IP 范围，恢复默认值，后续参数⽆无需填写
‣ 1：使能设置 IP 范围，后续参数必须填写
• <lease time>：租约时间，单位：分钟，取值范围 [1, 2880]
• <start IP>：DHCP 服务器器 IP 池的起始 IP
• <end IP>：DHCP 服务器器 IP 池的结束 IP
*示例：
AT+CWDHCPS_DEF=1,3,"192.168.4.10","192.168.4.15"
或者
AT+CWDHCPS_DEF=0 //清除设置，恢复默认值
*
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到Flash，1表示保存到Flash
*/
void moduleCWDHCPS(char *enable, char *leaseTime, char *startIP, char *endIP, uint8_t cmdType, uint8_t saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CWDHCPS_DEF, sizeof(WIFI_AT_CWDHCPS_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CWDHCPS_CUR, sizeof(WIFI_AT_CWDHCPS_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, enable);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, leaseTime);
        strcat(wifiATCmdString, ",");
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWAUTOCONN-上电是否自动连接 AP
本设置保存到 Flash 系统参数区。
*AT+CWAUTOCONN=<enable>
*
OK
*
<enable>：
‣ 0：上电不不⾃自动连接 AP
‣ 1： 上电⾃自动连接 AP
ESP8266 Station 默认上电⾃自动连接 AP。
*示例：
AT+CWAUTOCONN=1
*/
void moduleCWAUTOCONN(char *enable)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CWAUTOCONN, sizeof(WIFI_AT_CWAUTOCONN));
    strcat(wifiATCmdString, "=");
    strcat(wifiATCmdString, enable);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSTAMAC CUR-设置 ESP8266 $tation 当前 MAC 地址，不保存到 Flash
• 本设置不不保存到 Flash。
• ESP8266 SoftAP 和 Station 的 MAC 地址并不不相同，请勿将其设置为同⼀一 MAC 地址。
• ESP8266 MAC 地址第⼀一个字节的 bit 0 不不能为 1，例例如，MAC 地址可以为 "18:..." 但不不
能为 "15:..."。
*查询指令：
AT+CIPSTAMAC_CUR?
*返回值：
+CIPSTAMAC_CUR:<mac>
OK
*设置指令：
AT+CIPSTAMAC_CUR=<MAC>
*返回值：
OK
*参数说明：
<mac>：字符串串参数，ESP8266 Station 的 MAC 地址
*示例：
AT+CIPSTAMAC_CUR="18:fe:35:98:d3:7b"
*
*
*AT+CIPSTAMAC_DEF—设置 ESP8266 Station 当前 MAC 地址，保存到 Flash
• 本设置保存到 Flash ⽤用户参数区。
• ESP8266 SoftAP 和 Station 的 MAC 地址并不不相同，请勿将其设置为同⼀一 MAC 地址。
• ESP8266 MAC 地址第⼀一个字节的 bit 0 不不能为 1，例例如，MAC 地址可以为 "18:..." 但不不
能为 "15:..."。
*查询指令：
AT+CIPSTAMAC_DEF?
*返回值：
+CIPSTAMAC_DEF:<mac>
OK
*设置指令：
AT+CIPSTAMAC_DEF=<MAC>
*返回值：
OK
*参数说明：
<mac>：字符串串参数，ESP8266 Station 的 MAC 地址
*示例：
AT+CIPSTAMAC_DEF="18:fe:35:98:d3:7b"
*
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到Flash，1表示保存到Flash
*/
void moduleCIPSTAMAC(char *mac, uint8_t cmdType, uint8_t saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPSTAMAC_DEF, sizeof(WIFI_AT_CIPSTAMAC_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPSTAMAC_CUR, sizeof(WIFI_AT_CIPSTAMAC_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, mac);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPAPMAC_CUR-设置 ESP8266 SoftAP 当前 MAC 地址，不保存到 Flash
• 本设置不不保存到 Flash。
• ESP8266 SoftAP 和 Station 的 MAC 地址并不不相同，请勿将其设置为同⼀一 MAC 地址。
• ESP8266 MAC 地址第⼀一个字节的 bit 0 不不能为 1，例例如，MAC 地址可以为 "18:..." 但不不
能为 "15:..."。
*查询指令：
AT+CIPAPMAC_CUR?
*返回值：
+CIPAPMAC_CUR:<mac>
OK
*设置指令：
AT+CIPAPMAC_CUR=<MAC>
*返回值：
OK
*参数说明：
<mac>：字符串串参数，ESP8266 SoftAP 的 MAC 地址
*示例：
AT+CIPAPMAC_CUR="1a:fe:36:97:d5:7b"
*
*
*AT+CIPAPMAC DEF-设置 ESP8266 SoftAP 默认 MAC 地址，保存到 Flash
• 本设置不不保存到 Flash。
• ESP8266 SoftAP 和 Station 的 MAC 地址并不不相同，请勿将其设置为同⼀一 MAC 地址。
• ESP8266 MAC 地址第⼀一个字节的 bit 0 不不能为 1，例例如，MAC 地址可以为 "18:..." 但不不
能为 "15:..."。
*查询指令：
AT+AT+CIPAPMAC DEF?
*返回值：
+AT+CIPAPMAC DEF:<mac>
OK
*设置指令：
AT+AT+CIPAPMAC DEF=<MAC>
*返回值：
OK
*参数说明：
<mac>：字符串串参数，ESP8266 SoftAP 的 MAC 地址
*示例：
AT+AT+CIPAPMAC DEF="1a:fe:36:97:d5:7b"
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到Flash，1表示保存到Flash
*/
void moduleCIPAPMAC(char *mac, uint8_t cmdType, uint8_t saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPAPMAC_DEF, sizeof(WIFI_AT_CIPAPMAC_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPAPMAC_CUR, sizeof(WIFI_AT_CIPAPMAC_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, mac);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPSTA_CUR一设置 ESP8266 $tation 的IP 地址，不保存到 Flash
• 本设置不不保存到 Flash。
• 本设置指令与设置 DHCP 的指令（AT+CWDHCP 系列列）互相影响：
    ‣ 设置静态 IP，则 DHCP 关闭；
    ‣ 设置使能 DHCP，则静态 IP ⽆无效；
    ‣ 以最后的设置为准。
*查询指令：
AT+CIPSTA_CUR?
注意：ESP8266 Station IP 需连上 AP 后，才可以查询。
*返回值：
+CIPSTA_CUR:<ip>
+CIPSTA_CUR:<gateway>
+CIPSTA_CUR:<netmask>
OK
*设置指令：
AT+CIPSTA_CUR=<ip>[,<gateway>,<netmask>]
*返回值：
OK
*参数说明：
• <ip>：字符串串，ESP8266 Station 的 IP 地址
• [<gateway>]：⽹网关
• [<netmask>]：⼦子⽹网掩码
*示例：
AT+CIPSTA_CUR="192.168.6.100","192.168.6.1","255.255.255.0"
*
*
*AT+CIPSTA_DEF-设置 ESP8266 $tation 的 IP 地址，保存到 Flash
• 本设置保存到 Flash ⽤用户参数区。
• 本设置指令与设置 DHCP 的指令（AT+CWDHCP 系列列）互相影响：
    ‣ 设置静态 IP，则 DHCP 关闭；
    ‣ 设置使能 DHCP，则静态 IP ⽆无效；
    ‣ 以最后的设置为准。
*查询指令：
AT+CIPSTA_DEF?
注意：ESP8266 Station IP 需连上 AP 后，才可以查询。
*返回值：
+CIPSTA_DEF:<ip>
+CIPSTA_DEF:<gateway>
+CIPSTA_DEF:<netmask>
OK
*设置指令：
AT+CIPSTA_DEF=<ip>[,<gateway>,<netmask>]
*返回值：
OK
*参数说明：
• <ip>：字符串串，ESP8266 Station 的 IP 地址
• [<gateway>]：⽹网关
• [<netmask>]：⼦子⽹网掩码
*示例：
AT+CIPSTA_DEF="192.168.6.100","192.168.6.1","255.255.255.0"
*
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到Flash，1表示保存到Flash
*/
void moduleCIPSTA(char *ip, char *gateway, char *netmask, uint8_t cmdType, uint8_t saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPSTA_DEF, sizeof(WIFI_AT_CIPSTA_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPSTA_CUR, sizeof(WIFI_AT_CIPSTA_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, ip);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, gateway);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, netmask);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CIPAP CUR一设置 ESP8266 SoftAP 的IP 地址，不保存到 Flash
• 本设置保存到 Flash ⽤用户参数区。
• ⽬目前仅⽀支持 C 类 IP 地址。
• 本设置指令与设置 DHCP 的指令（AT+CWDHCP 系列列）互相影响：
    ‣ 设置静态 IP，则 DHCP 关闭；
    ‣ 设置使能 DHCP，则静态 IP ⽆无效；
    ‣ 以最后的设置为准。
*查询指令：
AT+CIPAP_CUR?
*返回值：
+CIPAP_CUR:<ip>
+CIPAP_CUR:<gateway>
+CIPAP_CUR:<netmask>
OK
*设置指令：
AT+CIPAP_DEF=<ip>[,<gateway>,<netmask>]
*返回值：
OK
*参数说明：
• <ip>：字符串串，ESP8266 SoftAP 的 IP 地址
• [<gateway>]：⽹网关
• [<netmask>]：⼦子⽹网掩码
*示例：
AT+CIPAP_CUR="192.168.5.1","192.168.5.1","255.255.255.0"
*
*
*AT+CIPAP DEF_设置 ESP8266 SoftAP 的 IP 地址，保存到 Flash
• 本设置保存到 Flash ⽤用户参数区。
• ⽬目前仅⽀支持 C 类 IP 地址。
• 本设置指令与设置 DHCP 的指令（AT+CWDHCP 系列列）互相影响：
    ‣ 设置静态 IP，则 DHCP 关闭；
    ‣ 设置使能 DHCP，则静态 IP ⽆无效；
    ‣ 以最后的设置为准。
*查询指令：
AT+CIPAP_DEF?
*返回值：
+CIPAP_DEF:<ip>
+CIPAP_DEF:<gateway>
+CIPAP_DEF:<netmask>
OK
*设置指令：
AT+CIPAP_DEF=<ip>[,<gateway>,<netmask>]
*返回值：
OK
*参数说明：
• <ip>：字符串串，ESP8266 SoftAP 的 IP 地址
• [<gateway>]：⽹网关
• [<netmask>]：⼦子⽹网掩码
*示例：
AT+CIPAP_DEF="192.168.5.1","192.168.5.1","255.255.255.0"
*
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到Flash，1表示保存到Flash
*/
void moduleCIPAP(char *ip, char *gateway, char *netmask, uint8_t cmdType, uint8_t saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPAP_DEF, sizeof(WIFI_AT_CIPAP_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CIPAP_CUR, sizeof(WIFI_AT_CIPAP_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, ip);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, gateway);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, netmask);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWSTARTSMART-开启 SmartConfig
****SmartConfig 连接过程中的提示信息如下：
    smartconfig type: <type> // AIRKISS, ESPTOUCH or UNKNOWN
    smart get wifi info // got SSID and password
    ssid:<AP's SSID>
    password:<AP's password>
    // ESP8266 will try to connect to the AP
    WIFI CONNECTED
    WIFI GOT IP
    smartconfig connected wifi // if the connection failed, it will prompt "smartconfig connect
    fail"
****• 仅⽀支持在 ESP8266 单 Station 模式下调⽤用。
    • 消息 smart get wifi info 表示 SmartConfig 成功获取到 AP 信息，之后 ESP8266 尝试
    连接 AP，打印连接过程。
    • 消息 smartconfig connected wifi 表示成功连接到 AP，此时可以调⽤用 AT+CWSTOPSMART
    停⽌止 SmartConfig 再执⾏行行其他指令。注意，在 SmartConfig 过程中请勿执⾏行行其他指令。
    • 从 AT_v1.0 开始，SmartConfig 可以⾃自动获取协议类型，AirKiss 或者 ESP-TOUCH。
    • ⽤用户如果⽆无需 SmartConfig 功能，可以参考章节 1.1 ⾃自⾏行行重新编译 at，在 user_config.h
    中关闭 CONFIG_AT_SMARTCONFIG_COMMAND_ENABLE，从⽽而减⼩小 bin size，节省内存。
*执行指令：
AT+CWSTARTSMART
*返回值：
OK
*设置指令：
AT+CWSTARTSMART=<type>
*返回值：
OK
*参数说明：
<type>：
‣ 1：ESP-TOUCH
‣ 2：AirKiss
‣ 3：ESP-TOUCH+AirKiss
*示例：
AT+CWMODE=1
AT+CWSTARTSMART
*
*
*AT+CWSTOPSMART-停止 SmartConfig
*返回值：OK
*注意：
⽆无论 SmartConfig 成功与否，都请调⽤用 AT+CWSTOPSMART 释放快连占⽤用的内存。
*示例：
AT+CWSTOPSMART
*
*stopFlag:0表示不停止，1表示停止
*/
void moduleCWSMART(char *type, uint8_t stopFlag)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (stopFlag)
    {
        memcpy(wifiATCmdString, WIFI_AT_CWSTOPSMART, sizeof(WIFI_AT_CWSTOPSMART));
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, type);
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CWSTARTSMART, sizeof(WIFI_AT_CWSTARTSMART));
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWSTARTDISCOVER一开启可被局域网内微信探测模式
本指令需在 ESP8266 Station 连⼊入局域⽹网，获得 IP 地址后⽣生效。
*AT+CWSTARTDISCOVER=<WeChat number>,<dev_type>,<time>
*返回值：
OK
*参数说明：
• <WeChat number>：微信公众号，必须从微信获取。
• <dev_type>：设备类型，必须从微信获取。
• <time>：主动发包时间间隔，取值范围：0 ~ 24x3600，单位：秒。
    ‣ 0：ESP8266 不不主动向外发包，需要⼿手机微信查询时才回复。
    ‣ 其他值：ESP8266 主动发包的时间间隔，以便便于局域⽹网中的⼿手机微信发现本设备。
*示例：
AT+CWSTARTDISCOVER="gh_9e2cff3dfa51","122475",10
*
*
*AT+CWSTOPDISCOVER一关闭可被局域网内微信探测模式
*返回值：OK
*示例：
AT+CWSTOPDISCOVER
*
*
*stopFlag:0表示不停止，1表示停止
*/
void moduleCWDISCOVER(char *WeChatNumber, char *devType, char *time, uint8_t stopFlag)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (stopFlag)
    {
        memcpy(wifiATCmdString, WIFI_AT_CWSTOPDISCOVER, sizeof(WIFI_AT_CWSTOPDISCOVER));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CWSTARTDISCOVER, sizeof(WIFI_AT_CWSTARTDISCOVER));
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, WeChatNumber);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, devType);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, time);
    }
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+WPS一设置 WPS 功能
• WPS 功能必须在 ESP8266 Station 使能的情况下调⽤用。
• WPS 不不⽀支持 WEP 加密⽅方式。
*AT+WPS=<enable>
*返回值：OK
*参数说明：
<enable>：
‣ 1：开启 WPS
‣ 0：关闭 WPS
*示例：
AT+CWMODE=1
AT+WPS=1
*/
void moduleWPS(char *enable)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_WPS, sizeof(WIFI_AT_WPS));
    strcat(wifiATCmdString, "=");
    strcat(wifiATCmdString, enable);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+MDNS-设置 MDNS 功能
    • <hostname> 和 <server_name> 不不能包含特殊字符（例例如 . 符号），或者设置为协议名称
    （例例如不不能定义为 http）。
    • ESP8266 SoftAP 模式暂时不不⽀支持 MDNS 功能。
*AT+MDNS=<enable>,<hostname>,<server_name>,<server_port>
*返回值：
OK
或
opmode mismatch when mdns
ERROR
*参数说明：
• <enable>：
‣ 1：开启 MDNS 功能，后续参数需要填写
‣ 0：关闭 MDNS 功能，后续参数⽆无需填写
• <hostname>：MDNS 主机名称
• <server_name>：MDNS 服务器器名称
• <server_port>：MDNS 服务器器端⼝
*示例：
AT+MDNS=1,"espressif","iot",8080
*/
void moduleMDNS(char *enable, char *hostname, char *serverName, char *serverPort)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_MDNS, sizeof(WIFI_AT_MDNS));
    strcat(wifiATCmdString, "=");
    strcat(wifiATCmdString, enable);
    strcat(wifiATCmdString, ",");
    strcat(wifiATCmdString, hostname);
    strcat(wifiATCmdString, ",");
    strcat(wifiATCmdString, serverName);
    strcat(wifiATCmdString, ",");
    strcat(wifiATCmdString, serverPort);
}

/*
*AT+CWHOSTNAME-设置 ESP8266 $tation 的主机名称
• 本设置不不保存到 Flash，重启后将恢复默认值。
• ESP8266 Station 默认的主机名称为 “ESP_MAC 地址低 3 个字节”。例如，
+CWHOSTNAME:<ESP_A378DA>。
*查询指令：
AT+CWHOSTNAME?
*返回值：
+CWHOSTNAME:<host name>
OK
如果未使能 ESP8266 Station 模式，则返
回
+CWHOSTNAME:<null>
OK
*设置指令：
AT+CWHOSTNAME=<host name>
*返回值：
如果成功，返回OK
如果未使能 ESP8266 station 模式，则提示ERROR
*参数说明：
<hostname>：主机名称，最⻓长 32 字节
*示例：
AT+CWMODE=3
AT+CWHOSTNAME="my_test"
*/
void moduleCWHOSTNAME(char *hostName)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    memcpy(wifiATCmdString, WIFI_AT_CWHOSTNAME, sizeof(WIFI_AT_CWHOSTNAME));
    strcat(wifiATCmdString, hostName);
    strcat(wifiATCmdString, "\r\n");
}

/*
*AT+CWCOUNTRY_CUR一设置 ESP8266 WiFi 国家码
• 本设置不不保存到 Flash，重启后将恢复默认值。
*查询指令：
AT+CWCOUNTRY_CUR?
*返回值：
+CWCOUNTRY_CUR:<country_policy>,<country_code>,<start_channel>,<total_channel_number>
OK
注意：
查询返回值为实际的国家码信息。如果设置为跟随 AP 切换，则查询值可能与之前的设置值不不同。
*设置指令：
AT+CWCOUNTRY_CUR=<country_policy>,<country_code>,<start_channel>,<total_channel_number>
*返回值：
OK
*参数说明：
<country_policy>:
• 0：根据 AP ⾃自动切换国家信息；
• 1：使⽤用设置的国家信息
<country_code>: 国家码字符串串，⻓长度最多⽀支持三个字符；第三个为特殊字符，在查询时不不
显示。
<start_channel> : 起始信道号
<total_channel_number> : 总信道个数
*示例：
AT+CWMODE=3
AT+CWCOUNTRY_CUR=1,"CN",1,5
*
*
*AT+CWCOUNTRY DEF-设置默认的 ESP8266 WiFi 国家码，并保存到 flash
• 本设置保存到 Flash，重启后仍然有效。
*查询指令：
AT+CWCOUNTRY_DEF?
*返回值：
+CWCOUNTRY_DEF:<country_policy>,<country_code>,<start_channel>,<total_channel_number>
OK
注意：查询返回值为保存在 flash 的默认国家码信息。即使设置为跟随 AP 切换，查询值仍然与之前的设置值⼀致。
*设置指令：
AT+CWCOUNTRY_DEF=<country_policy>,<country_code>,<start_channel>,<total_channel_number>
*返回值：
OK
*参数说明：
<country_policy>:
• 0：根据 AP ⾃自动切换国家信息；
• 1：使⽤用设置的国家信息
<country_code>: 国家码字符串串，⻓长度最多⽀支持三个字符；第三个为特殊字符，在查询时不不
显示。
<start_channel> : 起始信道号
<total_channel_number> : 总信道个数
*示例：
AT+CWMODE=3
AT+CWCOUNTRY_DEF=1,"CN",1,13
*
*
*cmdType:0表示查询，1表示设置
*saveType:0表示不保存到flash，1表示保存到flash
*/
void moduleCWCOUNTRY(char *countryPolicy, char *countryCode, char *startChannel, char *totalChannelNumber, char cmdType, char saveType)
{
    memset(wifiATCmdString, 0, WIFI_AT_CMD_MAX_LEN);
    if (saveType)
    {
        memcpy(wifiATCmdString, WIFI_AT_CWCOUNTRY_DEF, sizeof(WIFI_AT_CWCOUNTRY_DEF));
    }
    else
    {
        memcpy(wifiATCmdString, WIFI_AT_CWCOUNTRY_CUR, sizeof(WIFI_AT_CWCOUNTRY_CUR));
    }
    if (cmdType)
    {
        strcat(wifiATCmdString, "=");
        strcat(wifiATCmdString, countryPolicy);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, countryCode);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, startChannel);
        strcat(wifiATCmdString, ",");
        strcat(wifiATCmdString, totalChannelNumber);
    }
    else
    {
        strcat(wifiATCmdString, "?");
    }
    strcat(wifiATCmdString, "\r\n");
}
